package com.gjy.concurrency.aotmic;

import org.junit.jupiter.api.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.*;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-03-08 09:18:38
 */
public class Atomic3Test {

    private static final ExecutorService pool = Executors.newCachedThreadPool();

    @Test
    public void test5() {
        final String a = "A";
        AtomicStampedReference<String> reference = new AtomicStampedReference<>(a, 1);

        boolean attemptStamp = reference.attemptStamp("A", 2);
        System.out.println("attemptStamp = " + attemptStamp);
        System.out.println("reference.getStamp() = " + reference.getStamp());

        boolean compareAndSet = reference.compareAndSet("A", "V", 2, 10);
        System.out.println("compareAndSet = " + compareAndSet);
        System.out.println("reference.getReference() = " + reference.getReference());

        System.out.println("reference.get(new int[]{1,2,10}) = " + reference.get(new int[1]));
    }

    @Test
    public void test4() {
        AtomicEntity atomicEntity = new AtomicEntity(1, "H", 21);
        AtomicMarkableReference<AtomicEntity> reference = new AtomicMarkableReference<>(atomicEntity, true);
        AtomicEntity a = new AtomicEntity(2, "A", 22);
        reference.set(a, false);

        System.out.println("reference.getReference() = " + reference.getReference());
        System.out.println("reference.isMarked() = " + reference.isMarked());

        reference.attemptMark(a, true);
        System.out.println("reference.getReference() = " + reference.getReference());
        System.out.println("reference.isMarked() = " + reference.isMarked());
    }

    @Test
    public void test1() throws Exception {
        DoubleAccumulator doubleAccumulator = new DoubleAccumulator(Double::sum, 0.0d);
        for (int i = 0; i < 1000; i++) {
            pool.submit(() -> doubleAccumulator.accumulate(1.0d));
        }
        TimeUnit.SECONDS.sleep(0);
        System.out.println("doubleAccumulator = " + doubleAccumulator);
    }

    @Test
    public void test3() throws Exception {
        DoubleAdder doubleAdder = new DoubleAdder();
        for (int i = 0; i < 1000; i++) {
            pool.submit(() -> doubleAdder.add(1.0d));
        }
        TimeUnit.SECONDS.sleep(1);
        System.out.println("doubleAccumulator = " + doubleAdder);
    }

    @Test
    public void test2() throws Exception {
        AtomicReference<Double> sum = new AtomicReference<>(0.0);
        for (int i = 0; i < 1000; i++) {
            pool.submit(() -> {
                sum.updateAndGet(v -> v + 1.0d);
            });
        }
        TimeUnit.SECONDS.sleep(1);
        System.out.println("doubleAccumulator = " + sum);
    }
}
